package com.hvilela.drawer;

import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import com.hvilela.Drawer;
import com.hvilela.Entry;

/**
 * @author Henrique de Souza Vilela
 * henrique.vilela@gmail.com
 */
public class Boxes extends Drawer {
	@Override
	public BufferedImage draw(BufferedImage image, List<Entry> entries) {
		List<Entry> copy = new Vector<Entry>();
		copy.addAll(entries);
		Collections.sort(copy);

		draw(image, copy, 0, 0, image.getWidth() - border, image.getHeight() - border, false);

		return image;
	}

	private void draw(BufferedImage image, List<Entry> entries, int x, int y, int width, int height, boolean invert) {
		if (entries.size() == 0) {
			return;
		} else if (entries.size() == 1) {
			try {
				Entry entry = entries.get(0);
				draw(image, entry, x, y, width, height);
			} catch (Exception exception) {
				exception.printStackTrace();
			}
		} else {
			double destinationRatio = width / (double) height;

			List<Entry> left = new Vector<Entry>();
			List<Entry> right = new Vector<Entry>();
			
			int sum = 0;
			for (Entry entry : entries) {
				sum += entry.getWeight();
			}

			int leftSum = 0;
			int rightSum = 0;
			for (Entry entry : entries) {
				if (rightSum + entry.getWeight() < leftSum + entry.getWeight()) {
					right.add(entry);
					rightSum += entry.getWeight();
				} else {
					left.add(entry);
					leftSum += entry.getWeight();
				}
			}

			if (invert) {
				List<Entry> tmp = left;
				left = right;
				right = tmp;
				
				leftSum = sum - leftSum;
			} else {
				Collections.reverse(left);
				Collections.reverse(right);
			}

			if (splitHorizontally(destinationRatio)) {
				int newWidth = (int) (width / (double) sum * leftSum);

				draw(image, left, x, y, newWidth, height, invert);
				draw(image, right, x + newWidth, y, width - newWidth, height, !invert);
			} else {
				int newHeight = (int) (height / (double) sum * leftSum);

				draw(image, left, x, y, width, newHeight, invert);
				draw(image, right, x, y + newHeight, width, height - newHeight, !invert);
			}
		}
	}

	protected boolean splitHorizontally(double ratio) {
		return ratio >= 1.333;
	}
}